package engine;

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

import queries.Document;

/**
 * Corpus for storing and managing search results,
 * queries and user feedback
 * 
 * @author Vika
 * @author ak2765
 */
public final class Corpus {

	private final WordFrequencies wordFrequencies = new WordFrequencies();
	
	private final InvertedWordList invertedWordList = new InvertedWordList();
	
	private final BiGramFrequencies positiveBiGramFrequencies = new BiGramFrequencies();
	
	private int documentIdSequence = 0;
	
	private WordWeightCalculator calculator = new WordWeightCalculator(invertedWordList);
	
	/**
	 * @return
	 */
	public List<String> getWordsSortedByRelevance() {
		List<WeightedWord> weightedPositiveWords = calculateWeight(this.wordFrequencies.getPositiveWords());
		
		Collections.sort(weightedPositiveWords, new Comparator<WeightedWord>() {

			public int compare(WeightedWord left, WeightedWord right) {
				return Double.compare(right.getWeight(), left.getWeight());
			}
		});
		
		List<String> relevantWords = new LinkedList<String>();
		
		for(WeightedWord weightedWord : weightedPositiveWords) {
			relevantWords.add(weightedWord.getWord());
		}
		
		return relevantWords;
	}
	
	/**
	 * @param words
	 * @return
	 */
	private List<WeightedWord> calculateWeight(List<String> words) {
		List<WeightedWord> weightedWords = new LinkedList<WeightedWord>();
		for(String word : words) {
			double weight = this.calculator.calculateWeight(word);
			
			weightedWords.add(new WeightedWord(word, weight));
		}
		
		return weightedWords;
	}

	/**
	 * @param doc
	 */
	public void addPositiveDocument(Document doc) {
		IndexedDocument indexedDocument = indexDocument(doc);
		
		addWordsFromDocument(indexedDocument.getTitleWords(), true);
		addWordsFromDocument(indexedDocument.getDescriptionWords(), true);
		
		positiveBiGramFrequencies.addTitleWords(indexedDocument.getTitleWords());
		positiveBiGramFrequencies.addDescriptionWords(indexedDocument.getDescriptionWords());
		
		invertedWordList.addPositiveDocument(indexedDocument);
	}
	
	/**
	 * @param doc
	 */
	public void addNegativeDocument(Document doc) {
		IndexedDocument indexedDocument = indexDocument(doc);
		
		addWordsFromDocument(indexedDocument.getTitleWords(), false);
		addWordsFromDocument(indexedDocument.getDescriptionWords(), false);

		invertedWordList.addNegativeDocument(indexedDocument);
	}
	
	/**
	 * @param doc
	 * @return
	 */
	private IndexedDocument indexDocument(Document doc) {
		documentIdSequence++;
		
		IndexedDocument indexedDocument = new IndexedDocument(
				documentIdSequence, doc, WordTokenizer.tokenize(doc.getTitle()), WordTokenizer.tokenize(doc.getDescription()));
		
		return indexedDocument;
	}
	
	/**
	 * @param words
	 * @param positiveWord
	 */
	private void addWordsFromDocument(List<String> words, boolean positiveWord) {
		for (String word : words) {
			if (positiveWord) {
				this.wordFrequencies.addPositiveWord(word);
			} else {
				this.wordFrequencies.addNegativeWord(word);	
			}
			
		}
	}

	/**
	 * @return
	 */
	public List<BiGram> getTheTenPercentMorePopularBiGrams() {
		return this.positiveBiGramFrequencies.getTheTenPercentMorePopularBiGrams();
	}
}
